#include "SBXReader.h"
#include <vector>
#include "StringUtil.h"
#include <boost/foreach.hpp>

SBXReader::SBXReader(wstring filename):TextReader(filename),m_PlayerStart(0)
{
}


SBXReader::~SBXReader(void)
{
	BOOST_FOREACH(GMFModel* model, this->m_Models){
		delete model;
	}
	if ( m_PlayerStart != 0 )
		delete m_PlayerStart;
	
}

bool SBXReader::Read()
{
	if ( !m_File)
		return false;

	wstring line;
	std::vector<wstring> result;
	
	if (m_File.is_open())
	{
		m_CurrentState = MAIN;
		while (! m_File.eof() )
		{
			getline (m_File,line);
			if ( m_CurrentState == MAIN )
			{
				size_t modelIndex = line.find(L"Model");
				if ( modelIndex == string::npos )
				{
					StringUtil::Split(line,L"=",result);
					if ( result.size() == 2 ){
						size_t firstNonWhiteSpace = result[0].find_first_not_of(L" \t");
						wstring key = result[0].substr(firstNonWhiteSpace);
						m_Properties[key]=result[1];
					}
					result.clear();
				}else{
					m_CurrentState = MODEL;
					if ( this->LevelHasProperty(L"cameraposition")){
						wstring location = GetLevelProperty(L"cameraposition");
						ParseSBXFloat3(location,&m_CameraPos.x,&m_CameraPos.y,&m_CameraPos.z);
					}

					if ( this->LevelHasProperty(L"camerarotation")){
						wstring location = GetLevelProperty(L"camerarotation");
						ParseSBXFloat3(location,&m_CameraRot.x,&m_CameraRot.y,&m_CameraRot.z);
					}
					m_CurrentProperties.clear();
				}
			}else if ( m_CurrentState == MODEL ){
				size_t braceIndex = line.find(L"}");
				if( braceIndex != string::npos){
					m_CurrentState = MAIN;
					if ( !ModelHasProperty(L"\"classname\"") )
					{
						GMFModel* model = new GMFModel();
						wstring fileLoc = GetModelProperty(L"path");
						model->SetFileLocation(fileLoc.substr(1,fileLoc.length()-2));
						
						wstring location = GetModelProperty(L"position");
						DAEFloat3 pos;
						ParseSBXFloat3(location,&pos.x,&pos.y,&pos.z);
						model->SetLocation(pos);
						
						DAEFloat3 rot;
						wstring rotation = GetModelProperty(L"rotation");
						ParseSBXFloat3(rotation,&rot.x,&rot.y,&rot.z);
						model->SetRotation(rot);

						DAEFloat3 sc;
						wstring scale = GetModelProperty(L"scale");
						ParseSBXFloat3(scale,&sc.x,&sc.y,&sc.z);
						model->SetScale(sc);

						if ( ModelHasProperty(L"\"animation\""))
						{
							wstring animation = GetModelProperty(L"\"animation\"");
							model->SetAnimation(animation.substr(1,animation.length()-2));
						}
						if ( ModelHasProperty(L"\"name\""))
						{
							wstring name = GetModelProperty(L"\"name\"");
							model->SetName(name.substr(1,name.length()-2));
						}
						m_Models.push_back(model);
					}else{
						wstring className = GetModelProperty(L"\"classname\"");
						if (className == L"\"info_playerstart\"")
						{
							m_PlayerStart = new GMFPlayerStart();
							wstring location = GetModelProperty(L"position");
							DAEFloat3 pos;
							ParseSBXFloat3(location,&pos.x,&pos.y,&pos.z);
							m_PlayerStart->SetPosition(pos);
						
							DAEFloat3 rot;
							wstring rotation = GetModelProperty(L"rotation");
							ParseSBXFloat3(rotation,&rot.x,&rot.y,&rot.z);
							m_PlayerStart->SetRotation(rot);
						}
					}
				}else{
					StringUtil::Split(line,L"=",result);
					if ( result.size() == 2 ){
						size_t firstNonWhiteSpace = result[0].find_first_not_of(L" \t");
						wstring key = result[0].substr(firstNonWhiteSpace);
						m_CurrentProperties[key]=result[1];
					}
					result.clear();
				}
			}
			
		}
		m_File.close();
	}
	return true;
}

bool SBXReader::ModelHasProperty( wstring key )
{
	std::map<wstring,wstring>::const_iterator it = m_CurrentProperties.find(key);
	return it != m_CurrentProperties.end();

}

wstring SBXReader::GetModelProperty( wstring key )
{
	std::map<wstring,wstring>::const_iterator it = m_CurrentProperties.find(key);
	if ( it != m_CurrentProperties.end()){
		return (*it).second;
	}else{
		return L"<error>";
	}
}

bool SBXReader::LevelHasProperty( wstring key )
{
	std::map<wstring,wstring>::const_iterator it = m_Properties.find(key);
	return it != m_Properties.end();

}

wstring SBXReader::GetLevelProperty( wstring key )
{
	std::map<wstring,wstring>::const_iterator it = m_Properties.find(key);
	if ( it != m_Properties.end()){
		return (*it).second;
	}else{
		return L"<error>";
	}
}

void SBXReader::ParseSBXFloat3(wstring& toParse, float* x, float* y, float* z){
	size_t startIndex = 0;

	size_t firstComma = toParse.find(L",");
	size_t secondComma = toParse.find(L",",firstComma+1);
	if ( firstComma != string::npos && secondComma != string::npos)
	{

		*x = (float)_tstof(toParse.substr(0,firstComma).c_str());
		*y = (float)_tstof(toParse.substr(firstComma+1,secondComma).c_str());
		*z = (float)_tstof(toParse.substr(secondComma+1).c_str());
	}
}